package chances.epg.navigator.controller;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;

import chances.epg.commons.log.EpgLogFactory;
import chances.epg.commons.utils.PathUtils;
import chances.epg.commons.utils.URLUtils;
import chances.epg.data.service.BizService;
import chances.epg.data.service.ContentService;
import chances.epg.entity.biz.Biz;
import chances.epg.entity.content.SubjectPage;
import chances.epg.navigator.AccessException;
import chances.epg.navigator.EpgConstants;
import chances.epg.navigator.context.AccessContext;
import chances.epg.navigator.service.AccessContextFactory;
import chances.epg.navigator.service.NavigateUrlFactory;
import chances.epg.navigator.service.TemplateConfigService;
import chances.epg.navigator.template.TemplateConfig;
import chances.epg.navigator.template.TemplateContext;

/**
 * 访问链接导航.
 * 
 * @author <a href="mailto:libf@chances.com.cn">libf</a>
 */
public abstract class AccessController {
	protected static final Logger logger = EpgLogFactory.getSystemLogger();

	@Autowired
	protected BizService bizService;

	@Autowired
	protected ContentService contentService;

	@Autowired
	protected NavigateUrlFactory navigateUrlFactory;

	@Autowired
	protected AccessContextFactory accessContextFactory;

	@Autowired
	protected TemplateConfigService templateConfigService;

	/**
	 * 设置请求上下文.
	 * 
	 * @param model
	 * @param request
	 * @param context
	 */
	protected void setAccessContext(ModelMap model, HttpServletRequest request, AccessContext context) {
		model.put(EpgConstants.EPG_CONTEXT, context);

	}

	protected void setTemplateContext(ModelMap model, HttpServletRequest request, TemplateContext context,
			AccessContext accessContext) {
		String templatePackagePath = context.getTemplatePackagePath();
		if (!templatePackagePath.startsWith("/")) {
			templatePackagePath = "/" + templatePackagePath;
		}

		// 模板包路径
		model.put(EpgConstants.EPG_TEMPALTE_PATH,
				PathUtils.join(request.getContextPath() + "/sites", templatePackagePath));

		// 模板参数
		model.put(EpgConstants.EPG_TEMPLATE_PARAM, context.getTemplateParams());
	}

	/**
	 * 内容详情页.
	 * 
	 * @param model
	 * @param request
	 * @param context
	 * @return
	 */
	protected String detail(ModelMap model, HttpServletRequest request, AccessContext context) {
		Biz biz = this.getCurBiz(context);
		if (biz == null) {
			logger.error("biz not found,uri:{}", request.getRequestURI());
			throw new AccessException(AccessException.ACC_BIZ_NOT_FOUND,
					"biz not found,biz code:" + context.getBizCode());
		}
		context.setBiz(biz);

		TemplateConfig templateConfig = this.getTemplateConfigOfDetail(biz, context.getContentType());

		// use default template
		if (templateConfig == null) {
			logger.debug("not found detault template for uri:{},use default template.", request.getRequestURI());
			templateConfig = this.templateConfigService.getDefaultTemplateConfigForDetail(context.getSiteCode(),
					context.getContentType());
		}

		TemplateContext templateContext = this.templateConfigService.createTemplateContext(templateConfig, context);

		// 设置上下文参数.
		this.setAccessContext(model, request, context);
		this.setTemplateContext(model, request, templateContext, context);

		logger.debug("find template for uri:{},template file path:{}",
				new Object[] { request.getRequestURI(), templateContext.getTemplateFilePath() });
		return templateContext.getTemplateFilePath();
	}

	/**
	 * 找父节点绑定的子模板.
	 * 
	 * @param biz
	 * @return
	 */
	private TemplateConfig getTemplateConfigOfDetail(Biz biz, String contentType) {
		String locateStr = biz.getLocateStr();
		if (StringUtils.isBlank(locateStr)) {
			return null;
		}

		String[] bizCodes = locateStr.split("#");
		if (bizCodes.length < 1) {
			return null;
		}

		TemplateConfig templateConfig = null;
		for (int i = bizCodes.length - 1; i >= 0; i--) {
			templateConfig = this.templateConfigService.getTemplateConfigForDetail(bizCodes[i], contentType);
			if (templateConfig != null) {
				break;
			}
		}

		return templateConfig;
	}

	/**
	 * 
	 * @param context
	 * @return
	 */
	protected Biz getCurBiz(AccessContext context) {
		Biz biz = this.bizService.getBizByCode(context.getBizCode());

		// 设置展示栏目访问链接
		if (biz != null) {
			biz.setUrl(navigateUrlFactory.generateURL(context, biz));
		}

		return biz;
	}

	
	protected void redirectSubject(AccessContext context, HttpServletRequest request, HttpServletResponse response,
			String itemCode) throws IOException {
		SubjectPage subjectPage = this.contentService.getDefaultPageOfSubject(itemCode);
		String url = this.navigateUrlFactory.generateSubjectUrl(context, subjectPage.getPageCode());
		redirectEpg(context,request,response,url);

		
	}
	/**
	 * 跳转到展示栏目页面.
	 * 
	 * @param request
	 * @param response
	 * @param context
	 * @param bizCode
	 * @throws IOException
	 */
	protected void redirectBiz(AccessContext context, HttpServletRequest request, HttpServletResponse response,
			String bizCode) throws IOException {
		String bizURL = navigateUrlFactory.generateBizURL(context, bizCode);
		redirectEpg(context,request,response,bizURL);
	}

	protected void redirectEpg(AccessContext context, HttpServletRequest request, HttpServletResponse response,
			String url) throws IOException {
		String aUrl = url;
		context.setDirect(AccessContext.DIRECT_FLAG);
		if (StringUtils.isNotBlank(request.getQueryString())) {
			aUrl = url + "?" + request.getQueryString();
		}
		response.sendRedirect(aUrl);
	}

	protected void redirectExternalUrl(HttpServletRequest request, HttpServletResponse response, AccessContext context,
			String externalUrl) throws IOException {
		// 跳转链接
		context.setDirect(AccessContext.DIRECT_FLAG);
		// EpgLogUtils.logAccess(request, context);//跳转之前记录访问日志

		String returnURL = request.getRequestURL().toString();

		String redirectUrl = externalUrl;
		if (!externalUrl.startsWith("http://")) {
			redirectUrl = request.getContextPath() + externalUrl;
			response.sendRedirect(redirectUrl);
		} else {
			redirectUrl = URLUtils.appendParam(redirectUrl, "returnUrl", returnURL);
			response.sendRedirect(redirectUrl);
		}
	}

	public TemplateContext getBizTemplateContext(HttpServletRequest request, AccessContext context) {
		TemplateConfig templateConfig = this.templateConfigService.getSelfTemplateConfig(context.getBizCode());
		Biz biz = this.getCurBiz(context);
		if (biz == null) {
			logger.error("biz not found,access uri:{}", request.getRequestURI());
			throw new AccessException(AccessException.ACC_BIZ_NOT_FOUND,
					"biz not found,biz code:" + context.getBizCode());
		}
		context.setBiz(biz);
		if (templateConfig == null) {
			logger.debug("find template from parent biz.");
			templateConfig = this.getTemplateConfigOfParent(biz);
		}

		if (templateConfig == null) {
			logger.error("not found tempalte for biz,access uri:{}", request.getRequestURI());
			throw new AccessException(AccessException.ACC_TEMPLATE_NOT_FOUND,
					"not found template for biz:" + context.getBizCode());
		}

		TemplateContext templateContext = this.templateConfigService.createTemplateContext(templateConfig, context);
		return templateContext;
	}

	/**
	 * 找父节点绑定的子模板.
	 * 
	 * @param biz
	 * @return
	 */
	protected TemplateConfig getTemplateConfigOfParent(Biz biz) {
		String locateStr = biz.getLocateStr();
		if (StringUtils.isBlank(locateStr)) {
			return null;
		}

		String[] bizCodes = locateStr.split("#");
		if (bizCodes.length < 2) {
			return null;
		}

		TemplateConfig templateConfig = null;
		for (int i = bizCodes.length - 2; i >= 0; i--) {
			templateConfig = this.templateConfigService.getParentTemplateConfig(bizCodes[i]);
			if (templateConfig != null) {
				logger.debug("founded template of parent biz:{}", bizCodes[i]);
				break;
			}
		}

		return templateConfig;
	}

}
